package com.ybwh.springboot2.util;

import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 批量操作的工具类
 * </p>
 *
 * @author fanbeibei
 * @version V1.0
 * @since 2019/9/24 16:29
 */
public class BatchActionUtil {

    private BatchActionUtil() {
    }

    /**
     * <pre>
     *     批量查询的包装
     *     主要是为了防止sql中in的值过多超过mysql参数缓存的大小造成性能低下,同事也可以防止sql过大
     * </pre>
     *
     * @param list        查询参数
     * @param BATCH       每批的量
     * @param batchAction 查询的逻辑
     * @param <E1>        参数类型
     * @param <E2>        返回的数据类型
     * @return
     */
    public static <E1, E2> List<E2> batchQueryWrap(List<E1> list, final int BATCH, BatchAction<E1, E2> batchAction) {
        if (null == list || 0 == list.size() || null == batchAction || BATCH <= 0) {
            throw new IllegalArgumentException();
        }

        List<E2> rList = new ArrayList<>(list.size());

        int j = 0;
        for (int i = BATCH; i < list.size(); i += BATCH) {
            List<E2> list0 = batchAction.query(list.subList(j, i));
            if (!CollectionUtils.isEmpty(list0)) {
                rList.addAll(list0);
            }

            j = i;
        }

        if (j <= list.size() - 1) {
            List<E2> list0 = batchAction.query(list.subList(j, list.size()));
            if (!CollectionUtils.isEmpty(list0)) {
                rList.addAll(list0);
            }
        }

        return rList;

    }

    /**
     * <pre>
     *    批量插入功能的包装。
     *    分批执行,防止sql过大造成超过mysql通信包的最大值
     * </pre>
     *
     * @param dataList    要批量插入的数据
     * @param BATCH       分批执行的批次大小
     * @param batchAction 批量动作
     * @return
     */
    public static <T> int batchInsertWrap(List<T> dataList, final int BATCH, BatchAction<T, ?> batchAction) {
        if (null == dataList || 0 == dataList.size() || null == batchAction || BATCH <= 0) {
            throw new IllegalArgumentException();
        }

        int insertRecordNum = 0;

        int j = 0;
        for (int i = BATCH; i < dataList.size(); i += BATCH) {
            insertRecordNum += batchAction.insert(dataList.subList(j, i));
            j = i;
        }

        if (j <= dataList.size() - 1) {
            insertRecordNum += batchAction.insert(dataList.subList(j, dataList.size()));
        }

        return insertRecordNum;
    }


    /**
     * 批量操作
     */
    public interface BatchAction<E1, E2> {
        /**
         * 小批查询
         *
         * @param list 查询参数
         * @return
         */
        default List<E2> query(List<E1> list) {
            return null;
        }


        /**
         * 小批插入
         *
         * @param list
         * @return
         */
        default int insert(List<E1> list) {
            return 0;
        }
    }
}
